第 2 课:TCP/UDP 协议
(七)数据传输
在上面我们介绍了 “网络寻址” 的原理,这里我们重点讲 “数据传输” 的原理。
假设现在通信的通道已经建立好了(绿色的三层),而我们现在要关心数据怎么传输。也就是上面提到的数据包中的最后一列。

实际的 web 服务中,不同的进程需要使用 不同的的端口,因此上面的数据包中还要加上目标端口
| 数据链路层头部 | 网络层头部 | 传输层头部 | 数据包 |
|---|---|---|---|
| 源 mac: LL-LL-AA | 源 IP:192.168.0.23 | 源端口:114 | |
| 目标 Mac:le-le-le | 目标 IP:192.168.1.44 | 目标端口:514 |
由此我们 从主机到主机间的通信,细化到了 进程和进程之间的通信。并且部分实现了 UDP 协议,当然 UDP 协议除了端口其实还需要数据包长度和校验值。
这就引出了一个问题,如果 A -> B 的网络环境不可靠,有数据包在中途丢失该怎么处理呢?
我们的思路如下:
- A 怎么知道 包丢了?B 告诉 A
- 丢了的包怎么办? 重传
因此 A 每发一个包,都必须收到 来自B 的 确认包 ACK, 如果在一定时间内没有收到 ACK,就重传,这叫 停止等待协议
但是这样发一次收一次的通讯速度太慢了,因此采取了 一边发一边收 同时进行的策略。
但是又出现了新的问题,如果不同的数据包走了不同的路由,导致了接受顺序和发出顺序不同,该怎么解决呢?

因此需要在数据包上加上序号,B 返回的 ACK 确认包上也要带上对应序号
注意,如果 B 发出了 ACK3 并且被A成功接受到了,即使 A 没有收到 ACK1、ACK2,也会认为数据包 1、2 已经被成功接受。这个机制叫 累计确认/累计应答。
这就又出现了一个新问题:如果A 传输的速度过快,B接受不过来该怎么办?
因此需要在 数据包 和 ACK 包 中都加上 窗口大小,表示自己的接受能力。
假如 B 返回的 ACK 包中的窗口大小 win = 5,表示最多 5 个数据包,那么 A 会把要发送的数据包分为这 4 类。
在下图中,一个数字代表一个数据包,随着 A 不断收到新的 ACK 确认号,蓝色窗口不断向右移动,A 只能不断发送蓝色窗口内还没被发送的数据包。

注意:B 返回给 A 的窗口大小不是固定的,因此途中蓝色窗口的大小会实时调整。
这个机制被称为:滑动窗口
滑动窗口用于 流量控制,解决的是接受能力的问题。
如果 B 的接受能力很大,但是网络环境不好,导致拥塞问题丢失了一些包,该怎么处理呢?
网路拥塞问题的解决依然依赖窗口机制,但是这个窗口大小不是由 B 告诉 A 的,而是 A 主动发包试探得到的,有很多复杂的算法。
最终A 发包的 实际窗口大小 取决于 拥塞窗口 和 滑动窗口 的最小值。
win = min(cwnd,rwnd)
A 在给 B 发送数据包之前,需要确认 B 在监听,网络通道已经建立,这依赖于 三次握手机制
下面是流程
| 状态 | 图示 |
|---|---|
| 准备状态 | ![]() |
| 第一次握手 | ![]() |
| 第二次握手 | ![]() |
| 第三次握手 | ![]() |
| 状态建立完成 | ![]() |




